Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support custom lookup function in request() #308

Merged
merged 4 commits into from
Apr 10, 2024

Conversation

Musinux
Copy link
Contributor

@Musinux Musinux commented Feb 29, 2024

Description

Support custom DNS lookup function. This is particularly useful to prevent user-controlled requests accessing internal services, by denying accessing requests where the resolved IP is not public.

Alternatives

This could also be implemented by using a custom preRequest hook, but directly supporting the Http.request lookup parameter is the most straightforward way to pass options to a specific request.

I've implemented tests and documented the parameter both in API.md and in the index.d.ts file, please tell me if there are other parts that I've missed! I didn't touch the package version out of caution.

Happy to discuss it.

@Musinux
Copy link
Contributor Author

Musinux commented Mar 1, 2024

The windows test don't pass but I don't think that's related to my changes?

Copy link
Contributor

@kanongil kanongil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quite nice PR submission.

I am not sure I see the need to handle the lookup option explicitly when it can be done with custom logic in the preRequest hook. This seems like a quite esoteric use case.

If we add this, then we should probably also support the family and hints options to allow all name resolution related options.

If we really want to go for this, I would probably rework the implementation to create an internal list of directly copied options, and iterate over this when copying the options over. Eg. ['secureProtocol', 'ciphers', 'lookup', 'family', 'hints'].

API.md Outdated
Comment on lines 151 to 152
- `lookup` - DNS lookup function. see [http.request(url[,options][,callback])](https://nodejs.org/api/http.html#httprequestoptions-callback). Defaults to [dns.lookup()](https://nodejs.org/api/dns.html#dnslookuphostname-options-callback).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This belongs in the request() section.

test/index.js Outdated
}
});
expect(dnsLookupCalled).to.equal(true);
flags.onCleanup = () => server.close();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onCleanup should be registered right after the server is created.

I see that this copies behaviour from other tests. Don't ask me why this has been done previously.

lib/index.js Outdated
@@ -61,6 +61,7 @@ internals.Client = class {
Hoek.assert(internals.isNullOrUndefined(options.beforeRedirect) || typeof options.beforeRedirect === 'function', 'options.beforeRedirect must be a function');
Hoek.assert(internals.isNullOrUndefined(options.redirected) || typeof options.redirected === 'function', 'options.redirected must be a function');
Hoek.assert(options.gunzip === undefined || typeof options.gunzip === 'boolean' || options.gunzip === 'force', 'options.gunzip must be a boolean or "force"');
Hoek.assert(options.lookup === undefined || typeof options.lookup === 'function', 'options.lookup must be a function');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we actually need to assert() this. We only check wreck specific options as it is.

@Musinux
Copy link
Contributor Author

Musinux commented Mar 25, 2024

Thanks for reviewing my PR!

If we add this, then we should probably also support the family and hints options to allow all name resolution related options.

If we really want to go for this, I would probably rework the implementation to create an internal list of directly copied options, and iterate over this when copying the options over. Eg. ['secureProtocol', 'ciphers', 'lookup', 'family', 'hints'].

Makes sense, I've adapted the code to reflect your suggestions.

Regarding the use-case, I'd argue having user-controlled URLs called by servers is not esoteric, and servers are probably more often than not vulnerable to SSRFs (Server Side Request Forgery). Having this option built-in makes one step towards a better support for preventing access to the internal network of a server ☺️ (While already supported by the preRequest hook I know). Let's say it's a better transitive support for all libraries that use libraries that use wreck 😅

@Musinux Musinux requested a review from kanongil March 26, 2024 10:21
Copy link
Contributor

@kanongil kanongil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good and thorough. Thanks for the contribution.

FYI, whether it is actually merged is not up to me.

@Marsup Marsup added this to the 18.1.0 milestone Apr 10, 2024
@Marsup Marsup added the feature New functionality or improvement label Apr 10, 2024
@Marsup Marsup merged commit b4b323e into hapijs:master Apr 10, 2024
12 of 15 checks passed
@Marsup
Copy link
Contributor

Marsup commented Apr 10, 2024

Nothing to add to what Gil said, thanks for your contribution, it's shipped!

@Marsup Marsup linked an issue Apr 10, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New functionality or improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

support custom lookup function in request()
3 participants